package cn.framelife.rainbow.db.creator.part;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import cn.framelife.rainbow.db.BaseTable;
import cn.framelife.rainbow.db.DatabaseMessage;
import cn.framelife.rainbow.db.entity.ClazzProperty;
import cn.framelife.rainbow.db.entity.ForeignKey;
import cn.framelife.rainbow.db.entity.ImportSet;
import cn.framelife.rainbow.db.entity.Property;
import cn.framelife.rainbow.db.entity.Type;
import cn.framelife.rainbow.util.FreemarkerUtil;
import cn.framelife.rainbow.util.StringUtil;

/**
 * 实体类生成对象
 * 
 * @author 潘广伟 p_3er@qq.com  
 * @date 2014-3-10 下午6:53:17
 */
public abstract class EntityCreator {
	protected DatabaseMessage databaseMessage;
	
	public void createCodeForEntity(ClazzProperty entity) throws Exception{
		FreemarkerUtil.createEntity(entity);
	}

	/**
	 * 生成实体类对象
	 *
	 * @param reverseProperty
	 * @param metaData
	 * @param tableName
	 * @throws Exception
	 */
	protected ClazzProperty createEntity(BaseTable table,String modulePackage) throws Exception {
		DatabaseMetaData metaData = table.getMetaData();
		String tableName = table.getTableName();
		/**
		 * 获取主键
		 */
		String pkName = table.getPKColumnName();

		/**
		 * 获取外键
		 */
		Map<String, ForeignKey> fks = table.getFKColumn();

		ResultSet rs = metaData.getColumns(null, "%", tableName,"%");

		List<Property> properties = new ArrayList<Property>();
		Set<String> imports = new ImportSet<String>();
		String columnName;
		String columnType;
		String columnComment;
		Type type;
		Type pkType = null;
		String importType;
		String javaType;
		String annotation;
		Property property;
		while (rs.next()) {
			columnName = rs.getString("COLUMN_NAME");
			columnType = rs.getString("TYPE_NAME");
			columnComment = rs.getString("REMARKS");

			type = databaseMessage.getCoversion().converJavaType(columnType.toUpperCase());
			importType = type.getJavaTypePackage();
			javaType = type.getJavaType();
			annotation = StringUtil.merge("@Column(name = \"",columnName,"\")");
			/**
			 * 主键
			 */
			if (columnName.equals(pkName)) {
				pkType = type;
				annotation = StringUtil.merge("@Id\r\n\t@GeneratedValue\r\n\t@Column(name = \"",
						columnName,"\", unique = true, nullable = false)");
			}

			/**
			 * 外键
			 */
			if (fks.get(columnName) != null) {
				javaType = StringUtil.tableName2ClassName(fks.get(
						columnName).getFkTableName());
				importType = StringUtil.merge(modulePackage,".entity",".",javaType);
				annotation = StringUtil.merge("@ManyToOne(fetch = FetchType.LAZY)\r\n\t@JoinColumn(name = \""
						,columnName,"\")");
				imports.add("javax.persistence.ManyToOne");
				imports.add("javax.persistence.FetchType");
				imports.add("javax.persistence.JoinColumn");
				
			}

			property = new Property();
			property.setColumnName(columnName);
			property.setName(StringUtil.columnName2ClassProperty(columnName));
			if(StringUtil.isNotEmpty(columnComment)){
				property.setComment(columnComment);
			}else{
				property.setComment(property.getName());
			}
			property.setType(javaType);
			property.setAnnotation(annotation);
			properties.add(property);

			imports.add(importType);
		}

		ClazzProperty entity = new ClazzProperty();
		entity.setProjectName(databaseMessage.getProjectName());
		entity.setPackageURL(StringUtil.merge(modulePackage,".entity"));
		entity.setImports(imports);
		entity.setClassName(StringUtil.tableName2ClassName(tableName));
		entity.setClassAnnotation(StringUtil.merge("@Entity\r\n@Table(name = \"",tableName,"\")"));
		entity.setProperties(properties);
		entity.setPkType(pkType);
		entity.setFks(fks);

		entity.setClassComment(table.getTableComment(tableName));
		
		return entity;
		
	}
	
	
	public abstract List<ClazzProperty> createEntities(List<String> tableNames,String modulePackage)throws Exception ;
	
	public abstract ClazzProperty getEntity(String tableName,String modulePackage) throws Exception;
}
